#include <ev.h>
#include <amqpcpp.h>
#include <amqpcpp/libev.h>
#include <openssl/ssl.h>
#include <openssl/opensslv.h>

int main()
{
    // 1. 创建底层事件循环，用于监控 I/O 事件
    auto *loop = EV_DEFAULT;

    // 2. 将 AMQP 框架与 libev 事件循环连接起来
    AMQP::LibEvHandler handler(loop);

    // 3. 定义 RabbitMQ 服务器地址，包含用户名、密码、IP 和端口
    AMQP::Address address("amqp://root:123456@127.0.0.1:5672/");
    
    // 4. 创建与 RabbitMQ 服务器的 TCP 连接
    AMQP::TcpConnection connection(&handler, address);

    // 5. 创建 AMQP 信道，负责发送和接收消息
    AMQP::TcpChannel channel(&connection);

    // 6. 声明交换机（Exchange），指定为 direct 类型，定义消息路由规则
    channel.declareExchange("test-exchange", AMQP::ExchangeType::direct)
        .onError([](const char *message) { // 交换机声明失败的回调
            std::cout << "声明交换机失败：" << message << std::endl;
            exit(0);
        })
        .onSuccess([](){ // 交换机声明成功的回调
            std::cout << "test-exchange 交换机创建成功！" << std::endl;
        });

    // 7. 声明队列（Queue），消息将通过此队列传递
    channel.declareQueue("test-queue")
        .onError([](const char *message) { // 队列声明失败的回调
            std::cout << "声明队列失败：" << message << std::endl;
            exit(0);
        })
        .onSuccess([](){ // 队列声明成功的回调
            std::cout << "test-queue 队列创建成功！" << std::endl;
        });

    // 8. 将交换机与队列绑定，指定路由键（Routing Key）
    channel.bindQueue("test-exchange", "test-queue", "test-queue-key")
        .onError([](const char *message) { // 绑定失败的回调
            std::cout << "test-exchange - test-queue 绑定失败：" << message << std::endl;
            exit(0);
        })
        .onSuccess([](){ // 绑定成功的回调
            std::cout << "test-exchange - test-queue 绑定成功！" << std::endl;
        });

    // 9. 向交换机发布 10 条消息，消息会路由到绑定的队列
    for (int i = 0; i < 10; i++) {
        std::string msg = "Hello mag--" + std::to_string(i);
        bool ret = channel.publish("test-exchange", "test-queue-key", msg); // 发布消息
        if (!ret) {
            std::cout << "publish 失败！\n"; // 发布消息失败的回调
        }
    }

    // 10. 启动 libev 事件循环，处理所有 I/O 事件
    ev_run(loop, 0);

    return 0;
}
